﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.ProviderBase;
using System.Configuration;
using Dal;
using Policlinica;
using NLog;


namespace ADONetDal
{
    abstract public class ADONetRepositoryBase<T> : IRepository<T> where T : BusinessObjectBase
    {
        private SqlConnection connect;
        private static Logger logger = LogManager.GetCurrentClassLogger();

        public ADONetRepositoryBase()
        {
            connect = new SqlConnection(ConfigurationManager.ConnectionStrings["StudentApplication"].ConnectionString);
        }

        public void OpenConnection()
        {
            try
            {
                connect.Open();
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
            }
        }

        public void CloseConnection()
        {
            connect.Close();
        }

        public SqlConnection GetConnection()
        {
            return connect;
        }

        public T Insert(T entity)
        {
            var cmd = GetInsertCommand(entity);
            OpenConnection();
            try
            {
                var sqlDataReader = cmd.ExecuteReader();
                using (sqlDataReader)
                    entity = sqlDataReader.Read() ? GetEntity(sqlDataReader) : null;
                logger.Trace("Запись данных в базу успешно произведена");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
            }
            CloseConnection();
            return entity;
        }

        public void Delete(int id)
        {
            var cmd = GetDeleteCommand(id);
            OpenConnection();
            try
            {
                cmd.ExecuteNonQuery();
                logger.Trace("Удаление данных из базы успешно произведено");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
            }
            CloseConnection();
        }

        public T Update(T entity)
        {
            var cmd = GetUpdateCommand(entity);
            OpenConnection();
            try
            {
                var sqlDataReader = cmd.ExecuteReader();
                using (sqlDataReader)
                    entity = sqlDataReader.Read() ? GetEntity(sqlDataReader) : null;
                logger.Trace("Обновление данных в базе успешно произведена");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
            }
            CloseConnection();
            return entity;  
        }

        public T GetById(int id)
        {
            var cmd = GetSelectCommand(id);
            T entity = null;
            OpenConnection();
            try
            {
                var sqlDataReader = cmd.ExecuteReader();
                using (sqlDataReader)
                    entity = sqlDataReader.Read() ? GetEntity(sqlDataReader) : null;
                logger.Trace("Поиск записи по идентификатору успешно произведен");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
            }
            CloseConnection();
            return entity;
        }

        public List<T> GetList()
        {
            List<T> list = new List<T>();
            var cmd = GetSelectAllCommand();
                OpenConnection();
            try
            {
                var sqlDataReader = cmd.ExecuteReader();
                using (sqlDataReader)
                    while (sqlDataReader.Read())
                        list.Add(GetEntity(sqlDataReader));
                logger.Trace("Получение списка всех записей успешно произведено");
            }
            catch(Exception e)
            {
                logger.Error(e.Message);
            }
            CloseConnection();
            return list;
        } 

        public List<T> GetByParameter(object parameter, string columnName)
        {
            List<T> list = new List<T>();
            var cmd = GetSelectByParameterCommand(parameter, columnName);
            OpenConnection();
            try
            {
                var sqlDataReader = cmd.ExecuteReader();
                using (sqlDataReader)
                    while (sqlDataReader.Read())
                        list.Add(GetEntity(sqlDataReader));
                logger.Trace("Поиск записей по указанному параметру успешно произведен");
            }
            catch (Exception e)
            {
                logger.Error(e.Message);
            }
            CloseConnection();
            return list;
        } 

        protected abstract SqlCommand GetInsertCommand(T entity);

        protected abstract SqlCommand GetDeleteCommand(int id);

        protected abstract SqlCommand GetUpdateCommand(T entity);

        protected abstract SqlCommand GetSelectCommand(int id);

        protected abstract SqlCommand GetSelectAllCommand();

        protected abstract SqlCommand GetSelectByParameterCommand(object parameter, string columnName);

        protected abstract T GetEntity(SqlDataReader sqlDataReader);
    }
}
